package com.nodecollege.cloud.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.nodecollege.cloud.common.constants.NCConstants;
import com.nodecollege.cloud.common.model.LoginUser;
import com.nodecollege.cloud.common.model.NCResult;
import com.nodecollege.cloud.common.model.po.ChatGroupUser;
import com.nodecollege.cloud.common.utils.RedisUtils;
import com.nodecollege.cloud.common.utils.ThreadUserUtils;
import com.nodecollege.cloud.netty.ChatHandler;
import com.nodecollege.cloud.service.ChatService;
import com.nodecollege.cloud.service.GroupUserService;
import io.netty.channel.Channel;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author LC
 * @date 2020/2/26 23:07
 */
@Slf4j
public abstract class ChatServiceAbstrat implements ChatService {

    /**
     * channel用户关联信息
     **/
    private static final String CHANNEL_ID_USER_ID_MAP = "chat:redis:channelIdUserIdMap:";
    /**
     * 用户channel关联信息 一个用户只能有一个连接
     **/
    private static final String USER_ID_CHANNEL_ID_MAP = "chat:redis:userIdChannelIdMap:";
    /**
     * 用户channel关联信息 一个用户只能有一个连接
     **/
    private static final Map<Long, List<Channel>> USER_ID_CHANNEL_MAP = new ConcurrentHashMap();
    /**
     * 群组-聊天信息， 防止频繁查库
     **/
    private static final String GROUP_ID_RECORD_MAP = "chat:redis:groupRecordMap:";

    @Autowired
    private GroupUserService groupUserService;

    @Autowired
    private RedisUtils redisUtils;

    /**
     * 发送消息
     */
    public void sendMsg(Long userId, NCResult result, Integer recordType) {
        List<Channel> channelList = USER_ID_CHANNEL_MAP.get(userId);
        if (channelList == null || channelList.isEmpty()) {
            return;
        }
        Iterator<Channel> it = channelList.iterator();
        while (it.hasNext()) {
            Channel channel = it.next();
            if (ChatHandler.GLOBAL_USERS.find(channel.id()) != null) {
                sendMsg(channel, result, recordType);
            } else {
                // 用户离线 删除channel
                it.remove();
            }
        }
        if (channelList.isEmpty()) {
            USER_ID_CHANNEL_MAP.remove(userId);
        }
    }

    /**
     * 发送消息
     */
    public void sendMsg(Channel channel, NCResult result, Integer recordType) {
        result.setCode("recordType-" + recordType);
        channel.writeAndFlush(new TextWebSocketFrame(JSONObject.toJSONString(result)));
    }

    /**
     * 发送消息
     */
    public void sendGroupMsg(Long groupId, NCResult result, Integer recordType) {
        List<ChatGroupUser> userList = groupUserService.getGroupUser(groupId);
        for (int i = 0; i < userList.size(); i++) {
            if (NCConstants.INT_NEGATIVE_1.equals(userList.get(i).getState())){
                continue;
            }
            sendMsg(userList.get(i).getUserId(), result, recordType);
        }
    }

    /**
     * 群发消息
     *
     * @param channelList
     * @param result
     */
    public void groupSendMsg(List<Channel> channelList, NCResult result, Integer recordType) {
        for (int i = 0; i < channelList.size(); i++) {
            result.setCode("recordType-" + recordType);
            channelList.get(i).writeAndFlush(new TextWebSocketFrame(JSONObject.toJSONString(result)));
        }
    }

    /**
     * 用户连接时保存用户连接信息
     */
    public void connect(Channel channel) {
        LoginUser loginUser = ThreadUserUtils.getLoginUser();
        // 从当前服务获取channel
        List<Channel> oldChannelList = USER_ID_CHANNEL_MAP.get(loginUser.getUserId());
        if (oldChannelList == null) {
            USER_ID_CHANNEL_MAP.put(loginUser.getUserId(), new ArrayList<>());
            oldChannelList = USER_ID_CHANNEL_MAP.get(loginUser.getUserId());
        }
        oldChannelList.add(channel);
    }
}
